package cn.scau.edu.software.lgh.service;

import cn.scau.edu.software.lgh.entity.NetWork;
import cn.scau.edu.software.lgh.entity.Route;
import cn.scau.edu.software.lgh.entity.RouteListData;

import javax.swing.plaf.synth.SynthSpinnerUI;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

public class RouteServiceImpl {

    /**
     * 生成一个路由器，未连接任何网络
     * @param routrId 路由器名，不得重复
     * @return
     */
    public static Route createRoute(String routrId){
        Timer timer = new Timer();
        Route route = new Route(routrId,timer);
        double delayTime = Math.random()*1000;
        System.out.println(delayTime);
        timer.schedule(new TimerTask(){
            @Override
            public void run() {
                if(route.getRouteId().equals("C")){
                    System.out.println(displayMessageOfRouteDataList(route));
                }
                Vector<Route> flowedRoute = new Vector<>();
                flowedRoute.add(route);
                sendUpdataMessageOfRoute(route,null,flowedRoute);
            }
        },(int)(1000+delayTime),30000);
        return route;
    }

    /**
     * 向生成的路由器加入已存在的网络
     * @param route 指定路由器
     * @param netWork 加入的网络
     * @return
     */
    public static boolean addNetWorkToRoute(Route route, NetWork netWork){
        if(route.getLinkedNetworks().add(netWork)){
            RouteListData routeListData = new RouteListData(netWork.getNetworkId(),1,null);
            route.getRouteListDatas().add(routeListData);
            return true;
        }else{
            return false;
        }
    }

    /**
     * 路由器发送路由信息，将信息推送到network
     * @param route 路由信息
     * @param netWork   用于判别不往路由信息来的方向发送路由表信息，水平分割。
     *                  null为路由更新，向各个所连接的network发送信息
     *                  为指定network时则判别，更新信息来自此network，不再向此network发送路由信息
     *                  这样避免形成环路
     */
    public static void sendUpdataMessageOfRoute(Route route,NetWork netWork,Vector<Route> flowedThroughRoute){
        Vector<NetWork> netWorks  = route.getLinkedNetworks();
        if(netWork==null){
            for(NetWork net:netWorks){
                NetworkSecviceImpl.getUpdataMessage(route,net,flowedThroughRoute);
            }
        }else{
            for(NetWork net:netWorks){
                if(net!=netWork){
                    NetworkSecviceImpl.getUpdataMessage(route,net,flowedThroughRoute);
                }
            }

        }
    }

    /**
     * 路由器接收到来自network的更新信息
     * @param sendRoute
     * @param receiveRoute
     * @param netWork 信息入口，用于水平分割
     */
    public static void getUpdataMessageOfNetwork(Route sendRoute,Route receiveRoute,NetWork netWork,Vector<Route> flowedThroughRoute){
        updataDataListOfRoute(sendRoute,receiveRoute);
        flowedThroughRoute.add(receiveRoute);
        Vector<NetWork> netWorks = receiveRoute.getLinkedNetworks();
        for(NetWork net:netWorks){
            sendUpdataMessageOfRoute(receiveRoute,netWork,flowedThroughRoute);
        }
    }

    /**
     * 更新路由表
     * @param sendRoute 发送的路由信息，先进行距离加1，下一跳的路由器更新，然后和接收信息的路由器的路由表进行合并
     * @param receiveRoute
     */
    public static void updataDataListOfRoute(Route sendRoute,Route receiveRoute){
        int isIncude = 0;
        synchronized(sendRoute){
            synchronized (receiveRoute){
                Vector<RouteListData> receiveRouteDataList  = receiveRoute.getRouteListDatas();
                Vector<RouteListData> sendRouteDataList = new Vector<>();
                for(RouteListData sendRouteData:sendRoute.getRouteListDatas()){
                    sendRouteDataList.add(new RouteListData(sendRouteData.getGoalNetwork(),sendRouteData.getDistance()+1,sendRoute));
                }
                for(RouteListData sendRouteData:sendRouteDataList) {
                    isIncude = 0;
                    for (RouteListData receiveRouteData : receiveRouteDataList) {
                        if (sendRouteData.getGoalNetwork().equals(receiveRouteData.getGoalNetwork())) {
                            if (sendRouteData.getDistance() < receiveRouteData.getDistance() && sendRouteData.getDistance()<16) {
                                receiveRouteData.setBeatToNextRoute(sendRouteData.getBeatToNextRoute());
                                receiveRouteData.setDistance(sendRouteData.getDistance());
                            }
                            isIncude = 1;
                        }
                    }
                    if (isIncude == 0 && sendRouteData.getDistance()<16) {
                        receiveRouteDataList.add(sendRouteData);
                    }
                }
            }
        }
    }

    /**
     * 返回指定路由器的路由表信息
     * @param route
     * @return
     */
    public static String displayMessageOfRouteDataList(Route route){
        String message = "";
        Vector<RouteListData> routeListDatas = new Vector<>();
        routeListDatas.addAll(route.getRouteListDatas());
        for(RouteListData routeListData:routeListDatas){
            message=message+"network:"+routeListData.getGoalNetwork()
                    +" distance:"+routeListData.getDistance()
                    +" next route:";
            if(routeListData.getBeatToNextRoute()==null){
                message=message+"直接交付\n";
            }else {
                message=message+routeListData.getBeatToNextRoute().getRouteId()+"\n";
            }
        }
        return message;
    }

}
